<?php

namespace App\Http\Controllers\Admin\Finance;

use App\Exceptions\AppException;
use App\Http\Controllers\Controller;
use App\Models\AgentModel;
use App\Models\airline\base\FlightModel as BaseFlightModel;
use App\Models\airline\base\RouteModel;
use App\Models\base\CurrencyModel;
use App\Models\base\SubjectModel;
use App\Models\FlightItemModel;
use App\Models\FlightModel;
use App\Models\OrderModel;
use App\Models\PayBillIdsModel;
use App\Models\PayBillModel;
use App\Models\TakeOrderModel;
use App\Models\TakeOrderPayModel;
use App\Models\TakeOrderRecModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class Payable extends Controller
{
    
    public function take_orders(Request $request) {
        $page = $request->input('page', 1);
        $limit = $request->input('limit', 10);


        $query = (function() use ($request) {
            $des_country_id = $request->input('countrie_id', 0);
            $customer_name = $request->input('customer_name', '');
            $airline_id = $request->input('airline_id', '');
            $flight_number = $request->input('flight_number', '');
            $status = $request->input('status', '');
            $sn = $request->input('sn', []);
            $order_sn = $request->input('order_sn', []);
    
            $query = TakeOrderModel::query();
    
            if($des_country_id) {
                $query->whereIn('flight_id', function($query) use ($des_country_id){
                    $query->select('flight_id')
                        ->from((new FlightItemModel())->getTable())
                        ->where('destination_id', $des_country_id);
                });
            }
    
            if($customer_name) {
                $query->whereHas('customer', function($query) use ($customer_name) {
                    $query->where('name', 'like', '%'.$customer_name.'%');
                });
            }
    
            if($airline_id) {
                $query->whereIn('flight_id', function($query) use ($airline_id){
                    $query->select('flight_id')
                        ->from((new FlightItemModel())->getTable())
                        ->where('route_id', $airline_id);
                });
            }
    
            if($flight_number) {
                $query->whereIn('flight_id', function($query) use ($flight_number){
                    $query->select('flight_id')
                        ->from((new FlightItemModel())->getTable())
                        ->whereIn('airline_flight_id', function($query) use ($flight_number){
                            $query->select('id')
                                ->from((new BaseFlightModel())->getTable())
                                ->where('flight_number', $flight_number);
                        });
                });
            }
    
            if($status) {
                $query->where('status', $status);
            }

            if($sn && is_array($sn)) {
                $query->whereIn('sn', $sn);
            }

            if($order_sn && is_array($order_sn)) {
                $query->whereIn('id', function($query) use ($order_sn) {
                    $query->select('take_order_id')
                        ->from((new OrderModel())->getTable())
                        ->whereIn('sn', $order_sn);
                });
            }

            return $query;
        })();

        $total = $query->count('id');
        $items = $query
            ->withCount('orders')
            ->offset(($page-1) * $limit)
            ->limit($limit)
            ->orderBy('id', 'desc')
            ->get();

        $list = $items->map(function ($item) {
            $split_order_count = $item->orders->sum('split_order_addr_count');
            $pre_volume = $item->orders->sum('pre_volume');
            $storage_weight = $item->orders->sum('storage_weight');

            $flight_lines = $item->flight->items ?? null; //航班运力信息
            $start_port = $flight_lines?->first()->start_port?->name ?? ''; //始发港
            $des_country = $flight_lines?->first()->destination->name ?? ''; //目的地国家

            $route_ids = $flight_lines?->pluck('route_id') ?? [];
            $lines = RouteModel::whereIn('id', $route_ids)->pluck('name')->toArray(); //航线

            $airline_flight_ids = $flight_lines?->pluck('airline_flight_id') ?? [];
            $flight_no = BaseFlightModel::whereIn('id', $airline_flight_ids)->pluck('flight_number')->toArray(); //航班号

            return [
                'id' => $item->id,
                'customer_name' => $item->orders->first()->customer->name ?? '',
                'sn' => $item->sn,
                'start_port' => $start_port,
                'des_country' => $des_country,
                'split_order_count' => $split_order_count,
                'order_count' => $item->orders_count,
                'storage_weight' => $storage_weight,
                'pre_volume' => $pre_volume,
                'reality_weight' => $item->reality_weight2,
                'pay_amount' => '¥100, $20',
                'import_pay_amount' => '¥100, $20',
                'verify_status' => $item->verify_status == 2 ? '已核查' : '未核查',
                'pay_bill_status' => TakeOrderModel::PAY_BILL_STATUS[$item->pay_bill_status] ?? '',
                'pay_status' => TakeOrderModel::PAY_STATUS[$item->pay_status] ?? '',
                'flight_route' => implode(',', $lines),
                'flight_no' => implode(' ', $flight_no),
                'cargo_status' => FlightModel::STATUS_MAPS[$item->flight->status ?? null] ?? '',
                'take_off_time' => $item->flight->take_off_time ?? '',
                'hk_transport_time' => '-',
                'created_at' => $item->created_at?->toDateTimeString() ?? '',
                'settle_time' => $item->settle_time,
                'volume_weight' => $item->volume_weight2,
                'rec_p' => TakeOrderModel::$rec_p[$item->pay_p] ?? '',
                'fee_weight' => $item->fee_weight2,
                'set_weight_staff' => $item->set_weight_admin?->staff->name ?? '',
            ];
        });

        return $this->success(['list' => $list, 'total' => $total]);
    }

    //确认核查
    public function verify($id) {
        $take_order = TakeOrderModel::find($id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        $take_order->verify_status = 2;
        $take_order->save();

        TakeOrderPayModel::where('take_order_id', $id)->update(['verify_status' => 2]);

        return $this->success();
    }

    //取消核查
    public function cancel_verify($id) {
        $take_order = TakeOrderModel::find($id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        $take_order->verify_status = 1;
        $take_order->save();

        TakeOrderPayModel::where('take_order_id', $id)->update(['verify_status' => 2]);

        return $this->success();
    }

    //录入结算重
    public function set_weight(Request $request, $id) {
        $params = $request->all();

        $validator = Validator::make($params, [
            'reality_weight' => 'required|numeric',
            'volume_weight' => 'required|numeric',
            'fee_weight' => 'required|numeric',
            'rec_p' => 'required|in:1,2,3,4,5,6'
        ], [
            'reality_weight.required' => '请输入结算重',
            'volume_weight.required' => '请输入体积中',
            'rec_p.required' => '请选择是否收泡',
            'fee_weight.required' => '缺少计费重'
        ]);
    
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }

        $take_order = TakeOrderModel::find($id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        $take_order->reality_weight2 = $params['reality_weight'];
        $take_order->volume_weight2 = $params['volume_weight'];
        $take_order->fee_weight2 = $params['fee_weight'];
        $take_order->pay_p = $params['rec_p'];
        $take_order->settle_time2 = date('Y-m-d H:i:s');
        $take_order->save();

        return $this->success();
    }

    //确认结算重量
    public function confirm(Request $request, $id) {
        $take_order = TakeOrderModel::find($id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        $weight = $request->input('weight');
        if(!$weight) {
            return $this->error('结算重量不能为空');
        }

        DB::transaction(function() use ($take_order, $weight){
            $take_order->fee_weight2 = $weight;
            $take_order->save();
            
            // 计算航司费
            $flight = $take_order->flight;
            if(!$flight) {
                throw new AppException('提单航班信息错误');
            }
            foreach($flight->items as $line) {
                $air_company = $line->air_company;
                if(!$air_company) {
                    throw new AppException('航班航空公司错误');
                }
                $agent = $air_company->agent;
                if(!$agent) {
                    throw new AppException('航空公司服务提供商错误');
                }

                if($agent->type != AgentModel::AGENT_TYPE_AIRLINE) {
                    throw new AppException('航空公司类型错误');
                }
            }

        });

        return $this->success();
    }

    //成本录入
    public function add_pay(Request $request) {
        $ids = $request->input('ids');
        if(!is_array($ids) || empty($ids)) {
            return $this->success();
        }

        $items = $request->input('items', []);

        if(!is_array($items)) {
            return $this->success();
        }

        foreach($items as $item) {
            $validator = Validator::make($item, [
                'agent_id' => 'required|integer',
                'subject_id' => 'required|integer',
                'currency_id' => 'required|integer',
                'calc_type' => 'required|in:1,2,3',
                'amount' => 'required|numeric',
            ], [
                'agent_id.required' => '请选择费用类型',
                'subject_id.required' => '请选择费用科目',
                'currency_id.required' => '请选择币种',
                'calc_type.required' => '请选择计价方式',
                'amount.required' => '请填写金额/单价'
            ]);
        
            if ($validator->fails()) {
                return $this->error($validator->errors()->first());
            }

            $subject = SubjectModel::find($item['subject_id']);
            if(!$subject) {
                return $this->error('费用科目错误');
            }
    
            $currency = CurrencyModel::find($item['currency_id']);
            if(!$currency) {
                return $this->error('币种错误');
            }
    
            if($item['amount'] <= 0) {
                return $this->error('金额错误');
            }

        }

        $auth = $request->get('auth');
        DB::transaction(function() use ($items, $ids, $auth) {

            foreach($ids as $id) {
                $take_order = TakeOrderModel::find($id);
                if(!$take_order) {  continue; }

                foreach($items as $item) {
                    $currency = CurrencyModel::find($item['currency_id']);

                    TakeOrderPayModel::create([
                        'take_order_id' => $take_order->id,
                        'agent_id' => $item['agent_id'],
                        'currency' => $currency->short_code,
                        'symbol' => $currency->symbol,
                        'calc_type' => $item['calc_type'],
                        'type' => TakeOrderRecModel::TYPE_OTHER,
                        'subject_id' => $item['subject_id'],
                        'amount' => $item['amount'],
                        'remark' => $item['remark'] ?? '',
                        'created_admin_id' => $auth->id
                    ]);
                }


            }
        });

        return $this->success();
    }

    //应付明细
    public function pay_info(Request $request, $id) {
        $items = TakeOrderPayModel::where('take_order_id', $id)->get();

        $list = $items->map(function($item) {
            // $name = TakeOrderRecModel::TYPE_MAPS[$item->type] ?? '';
            // if($item->type == TakeOrderRecModel::TYPE_OTHER) {
            //     $subject = SubjectModel::find($item->subject_id);
            //     $name = '补录' . ($subject->name ?? '');
            // }

            $subject = SubjectModel::find($item->subject_id);

            return [
                'id' => $item->id,
                'agent_type' => AgentModel::TYPE_LIST[$item->agent->type ?? ''] ?? '',
                'agent_name' => $item->agent->name ?? '',
                'name' => $subject->name ?? '',
                'currency' => $item->currency,
                'import_amount' => $item->import_amount,
                'verify_status' => $item->verify_status == 2 ? '已核查' : '未核查',
                'bill_status' => $item->bill_status == 2 ? '已出账' : '未出账',
                'pay_status' => $item->pay_status == 2 ? '已付款' : '未付款',
                'create_user' => $item->create_admin->staff->name ?? '系统生成',
                'created_at' => $item->created_at->toDateTimeString(),
                'pay_time' => $item->pay_time,
                'remark' => $item->remark,

                'sys_amount' => $item->sys_amount,
                'amount' => $item->amount,
                'symbol' => $item->symbol,
                'create_user' => $item->create_admin->staff->name ?? '系统生成',
            ];
        });

        $collect = [];
        $collect2 = [];
        foreach($list as $item) {
            if(isset($collect[$item['symbol']])) {
                $collect[$item['symbol']] += $item['amount'];
            } else {
                $collect[$item['symbol']] = $item['amount'];
            }

            if(isset($collect2[$item['symbol']])) {
                $collect2[$item['symbol']] += $item['import_amount'];
            } else {
                $collect2[$item['symbol']] = $item['import_amount'];
            }
        }

        $result = '';
        foreach ($collect as $symbol => $value) {
            if (!empty($result)) {
                $result .= ", ";
            }
            $result .= $symbol . $value;
        }

        $result2 = '';
        foreach ($collect2 as $symbol => $value) {
            if (!empty($result2)) {
                $result2 .= ", ";
            }
            $result2 .= $symbol . $value;
        }


        return $this->success([
            'list' => $list,
            'total' => $result,
            'total2' => $result2
        ]);

    }

    //删除费用
    public function del_pay($id) {
        $rec = TakeOrderPayModel::find($id);
        if(!$rec) {
            return $this->success();
        }

        if($rec->type != TakeOrderRecModel::TYPE_OTHER) {
            return $this->error('非补录费用不能删除');
        }

        TakeOrderPayModel::destroy($id);
        return $this->success();
    }

    //确认核查
    public function confirm_pay($id) {
        $rec = TakeOrderPayModel::find($id);
        if(!$rec) {
            return $this->success();
        }

        $rec->verify_status = 2;
        $rec->save();

        return $this->success();
    }

    //取消核查
    public function cancel_pay($id) {
        $rec = TakeOrderPayModel::find($id);
        if(!$rec) {
            return $this->success();
        }

        $rec->verify_status = 1;
        $rec->save();

        return $this->success();
    }

    //修改费用
    public function update_rec(Request $request, $id) {
        $rec = TakeOrderRecModel::find($id);
        if(!$rec) {
            return $this->success();
        }

        $rec->amount = $request->input('amount');
        $rec->save();
        return $this->success();
    }

    //生成账单
    public function create_bill(Request $request) {
        $ids = $request->input('ids');

        $take_orders = TakeOrderModel::whereIn('id', $ids)->get();

        $type = intval($request->input('type', ''));
        $agent_name = $request->input('agent_name', '');

        $agent_bill = [];
        foreach($take_orders as $take_order) {
            if($take_order->pay_bill_status != 1) {
                return $this->error($take_order->sn . '已出账,请勿重复出账');
            }
            //应付
            $query = TakeOrderPayModel::where('take_order_id', $take_order->id);
            if($type) {
                $query->whereHas('agent', function($query) use ($type) {
                    $query->where('type', $type);
                });
            }

            if($agent_name) {
                $query->whereHas('agent', function($query) use ($agent_name) {
                    $query->where('name', $agent_name);
                });
            }

            $pays = $query->get();

            $oft = 0;
            foreach($pays as $pay) {
                $agent_type = $pay->agent->type ?? '';
                if(empty($agent_type)) { continue; }

                $key = $pay->agent_id . '_' . $pay->currency;
                if(isset($agent_bill[$key])) {
                    $agent_bill[$key]['amount'] += $pay->amount;
                    if($oft == 0) {
                        $agent_bill[$key]['take_order_count']++;
                    }
                } else {
                    $agent_bill[$key] = [
                        'key' => $key,
                        'agent_name' => $pay->agent->name ?? '',
                        'type' => AgentModel::TYPE_LIST[$agent_type] ?? '',
                        'currency' => $pay->currency,
                        'symbol' => $pay->symbol,

                        'amount' => $pay->amount,
                        'take_order_count' => 1,
                    ];
                }
                $oft = 1;
            }
        }

        $total = [];
        foreach($agent_bill as $key => $item) {
            if(isset( $total[$item['symbol']])) {
                $total[$item['symbol']] += $item['amount'];
            } else {
                $total[$item['symbol']] = $item['amount'];
            }
        }

        $res = [];
        foreach($total as $symbol => $value) {
            $res[] = $symbol . $value;
        }

        $list = array_values($agent_bill);
        return $this->success(['list' => $list, 'total' => implode(',', $res)]);
    }

    //确认生成账单
    public function confirm_bill(Request $request) {
        $ids = $request->input('ids');
        if(!is_array($ids) || empty($ids)) {
            return $this->success();
        }
        $remarks = $request->input('remarks');
        if(!is_array($remarks)) {
            $remarks = [];
        }

        $remarks = array_column($remarks, null, 'key');
        $start = $request->input('start', '');
        $end = $request->input('end', '');

        if(empty($start) || empty($end)) {
            return $this->error('请选择账单周期');
        }

        $take_orders = TakeOrderModel::whereIn('id', $ids)->get();

        $agent_bill = [];
        foreach($take_orders as $take_order) {
            if($take_order->pay_bill_status != 1) {
                return $this->error($take_order->sn . '已出账,请勿重复出账');
            }

            $pays = TakeOrderPayModel::where('take_order_id', $take_order->id)->get();
            $oft = 0;
            foreach($pays as $pay) {
                $agent_type = $pay->agent->type ?? '';
                if(empty($agent_type)) { continue; }
                
                $key = $pay->agent_id . '_' . $pay->currency;
                $remark = $remarks[$key]['remark'] ?? '';

                if(isset($agent_bill[$key])) {
                    $agent_bill[$key]['amount'] += $pay->amount;
                    if($oft == 0) {
                        $agent_bill[$key]['take_order_count']++;
                    }
                } else {
                    $agent_bill[$key] = [
                        'key' => $key,
                        'agent_id' => $pay->agent_id,
                        'remark' => $remark,
                        'agent_name' => $pay->agent->name ?? '',
                        'type' => AgentModel::TYPE_LIST[$agent_type] ?? '',
                        'currency' => $pay->currency,
                        'symbol' => $pay->symbol,

                        'amount' => $pay->amount,
                        'take_order_count' => 1,
                    ];
                }
                $oft = 1;
            }
        }

        $auth = $request->get('auth');
        DB::transaction(function() use ($agent_bill, $start, $end, $auth, $take_orders){
            foreach($agent_bill as $bill) {
                $pay_bill = new PayBillModel();
                $pay_bill->agent_id = $bill['agent_id'];
                $pay_bill->currency = $bill['currency'];
                $pay_bill->symbol = $bill['symbol'];
                $pay_bill->amount = $bill['amount'];
                $pay_bill->actual_amount = $bill['amount'];
                $pay_bill->remark = $bill['remark'] ?? '';
                $pay_bill->start = $start;
                $pay_bill->end = $end;
                $pay_bill->created_admin_id = $auth->id;
                $pay_bill->save();
                $pay_bill->sn = 'YF' . date('Ymd') . $pay_bill->id;
                $pay_bill->save();
            }

            //提单出账状态改为已出账
            TakeOrderModel::whereIn('id', $take_orders->pluck('id'))->update([
                'pay_bill_status' => 2
            ]);

            foreach(array_unique($take_orders->pluck('id')->toArray()) as $take_order_id) {
                $ids = new PayBillIdsModel();
                $ids->pay_bill_id = $pay_bill->id;
                $ids->take_order_id = $take_order_id;
                $ids->save();
            }

        });

        return $this->success();

    }

}
